From 93344f6dfee0d21e5e9aa750b5a91ed10980cd24 Mon Sep 17 00:00:00 2001 From: Owen Taylor Date: Thu, 3 Feb 2005 23:29:02 +0000 Subject: [PATCH] Add gdk_drawable_set_cairo_target(). 2005-02-03 Owen Taylor * gdk/gdkdrawable.[ch] gdkpixmap.c gdkwindow.c: Add gdk_drawable_set_cairo_target(). * tests/testtreeflow.c (enum): Use grand not rand as a variable name because one of the cairo headers is pulling in stdlib.h. * tests/testcairo.c tests/Makefile.am: Add a simple cairo based example. * configure.in: Bump release to 2.7.0, gtk_binary_version to 2.7.0. * Require libpangocairo for all backends. --- ChangeLog | 15 ++ ChangeLog.pre-2-10 | 15 ++ ChangeLog.pre-2-8 | 15 ++ configure.in | 22 +- docs/reference/gdk/tmpl/gdkdisplay.sgml | 11 + docs/reference/gdk/tmpl/x_interaction.sgml | 9 + .../gtk/tmpl/gtkcellrendererpixbuf.sgml | 5 + .../gtk/tmpl/gtkcellrenderertext.sgml | 10 + docs/reference/gtk/tmpl/gtkstock.sgml | 11 + gdk/gdkdraw.c | 23 ++ gdk/gdkdrawable.h | 9 +- gdk/gdkpixmap.c | 12 + gdk/gdkwindow.c | 24 ++ gdk/x11/gdkdrawable-x11.c | 50 ++++ gdk/x11/gdkdrawable-x11.h | 1 + gdk/x11/gdkpixmap-x11.c | 6 + gdk/x11/gdkwindow-x11.c | 11 +- tests/.cvsignore | 1 + tests/Makefile.am | 3 + tests/testcairo.c | 243 ++++++++++++++++++ tests/testtreeflow.c | 14 +- 21 files changed, 489 insertions(+), 21 deletions(-) create mode 100644 tests/testcairo.c diff --git a/ChangeLog b/ChangeLog index 1564d3fe84..579b02923d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2005-02-03 Owen Taylor + + * gdk/gdkdrawable.[ch] gdkpixmap.c gdkwindow.c: Add + gdk_drawable_set_cairo_target(). + + * tests/testtreeflow.c (enum): Use grand not rand as a variable + name because one of the cairo headers is pulling in stdlib.h. + + * tests/testcairo.c tests/Makefile.am: Add a simple cairo based + example. + + * configure.in: Bump release to 2.7.0, gtk_binary_version to 2.7.0. + + * Require libpangocairo for all backends. + 2005-02-03 Tor Lillqvist * modules/input/gtkimcontextime.c (get_pango_attr_list): Use the diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index 1564d3fe84..579b02923d 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,18 @@ +2005-02-03 Owen Taylor + + * gdk/gdkdrawable.[ch] gdkpixmap.c gdkwindow.c: Add + gdk_drawable_set_cairo_target(). + + * tests/testtreeflow.c (enum): Use grand not rand as a variable + name because one of the cairo headers is pulling in stdlib.h. + + * tests/testcairo.c tests/Makefile.am: Add a simple cairo based + example. + + * configure.in: Bump release to 2.7.0, gtk_binary_version to 2.7.0. + + * Require libpangocairo for all backends. + 2005-02-03 Tor Lillqvist * modules/input/gtkimcontextime.c (get_pango_attr_list): Use the diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index 1564d3fe84..579b02923d 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,18 @@ +2005-02-03 Owen Taylor + + * gdk/gdkdrawable.[ch] gdkpixmap.c gdkwindow.c: Add + gdk_drawable_set_cairo_target(). + + * tests/testtreeflow.c (enum): Use grand not rand as a variable + name because one of the cairo headers is pulling in stdlib.h. + + * tests/testcairo.c tests/Makefile.am: Add a simple cairo based + example. + + * configure.in: Bump release to 2.7.0, gtk_binary_version to 2.7.0. + + * Require libpangocairo for all backends. + 2005-02-03 Tor Lillqvist * modules/input/gtkimcontextime.c (get_pango_attr_list): Use the diff --git a/configure.in b/configure.in index 54801f92eb..fd1d9264d1 100644 --- a/configure.in +++ b/configure.in @@ -11,11 +11,11 @@ AC_PREREQ(2.54) # set GTK_BINARY_AGE and GTK_INTERFACE_AGE to 0. m4_define([gtk_major_version], [2]) -m4_define([gtk_minor_version], [6]) -m4_define([gtk_micro_version], [2]) +m4_define([gtk_minor_version], [7]) +m4_define([gtk_micro_version], [0]) m4_define([gtk_version], [gtk_major_version.gtk_minor_version.gtk_micro_version]) -m4_define([gtk_interface_age], [2]) +m4_define([gtk_interface_age], [0]) m4_define([gtk_binary_age], [m4_eval(100 * gtk_minor_version + gtk_micro_version)]) # This is the X.Y used in -lgtk-FOO-X.Y @@ -26,7 +26,7 @@ m4_define([gtk_api_version], [2.0]) # locations. (Should this be backwards-compat instead?) # #GTK_BINARY_VERSION=$GTK_MAJOR_VERSION.$GTK_MINOR_VERSION.$LT_CURRENT -m4_define([gtk_binary_version], [2.4.0]) +m4_define([gtk_binary_version], [2.7.0]) # required versions of other packages m4_define([glib_required_version], [2.6.0]) @@ -1403,7 +1403,7 @@ fi # if test "x$gdktarget" = "xx11"; then - PANGO_PACKAGES=pangoxft + PANGO_PACKAGES="pangoxft pangocairo" # We no longer use pangox, but if we find it, we link to it # for binary compatibility. @@ -1411,11 +1411,11 @@ if test "x$gdktarget" = "xx11"; then PANGO_PACKAGES="$PANGO_PACKAGES pangox" fi elif test "x$gdktarget" = "xwin32"; then - PANGO_PACKAGES=pangowin32 + PANGO_PACKAGES="pangowin32 pangocairo" elif test "x$gdktarget" = "xlinux-fb"; then - PANGO_PACKAGES=pangoft2 + PANGO_PACKAGES="pangoft2 pangocairo" else - PANGO_PACKAGES=pango + PANGO_PACKAGES="pango pangocairo" fi # Check for Pango flags @@ -1428,10 +1428,8 @@ if $PKG_CONFIG --exists $PANGO_PACKAGES ; then AC_MSG_RESULT($PANGO_CFLAGS $PANGO_LIBS) else AC_MSG_ERROR([ -*** Pango not found. Pango is required to build GTK+. -*** See http://www.pango.org for Pango information. -*** For the framebuffer target, you will need to build -*** Pango with freetype support. +*** Pango not found. Pango built with Cairo support is required +*** to build GTK+. See http://www.pango.org for Pango information. ]) fi diff --git a/docs/reference/gdk/tmpl/gdkdisplay.sgml b/docs/reference/gdk/tmpl/gdkdisplay.sgml index 8c87f9e058..b0908fbdba 100644 --- a/docs/reference/gdk/tmpl/gdkdisplay.sgml +++ b/docs/reference/gdk/tmpl/gdkdisplay.sgml @@ -278,6 +278,17 @@ Applications should never have any reason to use this facility @Returns: + + + + + +@display: +@screen: +@x: +@y: + + diff --git a/docs/reference/gdk/tmpl/x_interaction.sgml b/docs/reference/gdk/tmpl/x_interaction.sgml index badef605cf..82ab674858 100644 --- a/docs/reference/gdk/tmpl/x_interaction.sgml +++ b/docs/reference/gdk/tmpl/x_interaction.sgml @@ -440,6 +440,15 @@ Since: 2.2 @timestamp: + + + + + +@display: +@Returns: + + diff --git a/docs/reference/gtk/tmpl/gtkcellrendererpixbuf.sgml b/docs/reference/gtk/tmpl/gtkcellrendererpixbuf.sgml index 7ff0da00d1..51da83bb0e 100644 --- a/docs/reference/gtk/tmpl/gtkcellrendererpixbuf.sgml +++ b/docs/reference/gtk/tmpl/gtkcellrendererpixbuf.sgml @@ -36,6 +36,11 @@ property is set to a pixbuf, it renders that one. + + + + + diff --git a/docs/reference/gtk/tmpl/gtkcellrenderertext.sgml b/docs/reference/gtk/tmpl/gtkcellrenderertext.sgml index feafc320ff..01b12175bb 100644 --- a/docs/reference/gtk/tmpl/gtkcellrenderertext.sgml +++ b/docs/reference/gtk/tmpl/gtkcellrenderertext.sgml @@ -237,6 +237,16 @@ the #GtkCellRendererText allows to edit its text using an entry. + + + + + + + + + + diff --git a/docs/reference/gtk/tmpl/gtkstock.sgml b/docs/reference/gtk/tmpl/gtkstock.sgml index ffd4d0451c..42485c6b67 100644 --- a/docs/reference/gtk/tmpl/gtkstock.sgml +++ b/docs/reference/gtk/tmpl/gtkstock.sgml @@ -96,6 +96,17 @@ used for right-to-left locales. @Returns: + + + + + +@domain: +@func: +@data: +@notify: + + The "About" item. diff --git a/gdk/gdkdraw.c b/gdk/gdkdraw.c index f547fad904..63951a024e 100644 --- a/gdk/gdkdraw.c +++ b/gdk/gdkdraw.c @@ -1221,6 +1221,29 @@ gdk_drawable_real_get_visible_region (GdkDrawable *drawable) return gdk_region_rectangle (&rect); } +/** + * gdk_drawable_set_cairo_target: + * @drawable: a #GdkDrawable + * @cr: a cairo context + * + * Sets the given drawable as the target surface for a Cairo context. + * Note that when @drawable is a window and gdk_window_begin_paint() + * has been called, the target surface will be set to the temporary + * backing pixmap, so you can only use the Cairo context until + * the matching call to gdk_window_end_paint(). + * + * Since: 2.10 + **/ +void +gdk_drawable_set_cairo_target (GdkDrawable *drawable, + cairo_t *cr) +{ + g_return_if_fail (GDK_IS_DRAWABLE (drawable)); + g_return_if_fail (cr != NULL); + + return GDK_DRAWABLE_GET_CLASS (drawable)->set_cairo_target (drawable, cr); +} + static void composite (guchar *src_buf, gint src_rowstride, diff --git a/gdk/gdkdrawable.h b/gdk/gdkdrawable.h index 3fb9ea846a..612ce694fd 100644 --- a/gdk/gdkdrawable.h +++ b/gdk/gdkdrawable.h @@ -6,6 +6,8 @@ #include #include +#include + #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ @@ -168,8 +170,10 @@ struct _GdkDrawableClass GdkTrapezoid *trapezoids, gint n_trapezoids); + void (*set_cairo_target) (GdkDrawable *drawable, + cairo_t *cr); + /* Padding for future expansion */ - void (*_gdk_reserved3) (void); void (*_gdk_reserved4) (void); void (*_gdk_reserved5) (void); void (*_gdk_reserved6) (void); @@ -388,6 +392,9 @@ GdkImage *gdk_drawable_copy_to_image (GdkDrawable *drawable, GdkRegion *gdk_drawable_get_clip_region (GdkDrawable *drawable); GdkRegion *gdk_drawable_get_visible_region (GdkDrawable *drawable); +void gdk_drawable_set_cairo_target (GdkDrawable *drawable, + cairo_t *cr); + gboolean gdk_draw_rectangle_alpha_libgtk_only (GdkDrawable *drawable, gint x, gint y, diff --git a/gdk/gdkpixmap.c b/gdk/gdkpixmap.c index 978712a9e0..d3012eb64e 100644 --- a/gdk/gdkpixmap.c +++ b/gdk/gdkpixmap.c @@ -144,6 +144,9 @@ static GdkImage* gdk_pixmap_copy_to_image (GdkDrawable *drawable, gint width, gint height); +static void gdk_pixmap_set_cairo_target (GdkDrawable *drawable, + cairo_t *cr); + static GdkVisual* gdk_pixmap_real_get_visual (GdkDrawable *drawable); static gint gdk_pixmap_real_get_depth (GdkDrawable *drawable); static void gdk_pixmap_real_set_colormap (GdkDrawable *drawable, @@ -224,6 +227,7 @@ gdk_pixmap_class_init (GdkPixmapObjectClass *klass) drawable_class->get_colormap = gdk_pixmap_real_get_colormap; drawable_class->get_visual = gdk_pixmap_real_get_visual; drawable_class->_copy_to_image = gdk_pixmap_copy_to_image; + drawable_class->set_cairo_target = gdk_pixmap_set_cairo_target; } static void @@ -517,6 +521,14 @@ gdk_pixmap_copy_to_image (GdkDrawable *drawable, width, height); } +static void +gdk_pixmap_set_cairo_target (GdkDrawable *drawable, + cairo_t *cr) +{ + gdk_drawable_set_cairo_target (((GdkPixmapObject*)drawable)->impl, + cr); +} + static GdkBitmap * make_solid_mask (GdkScreen *screen, gint width, gint height) { diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c index 41e5e2ab97..4a27988c67 100644 --- a/gdk/gdkwindow.c +++ b/gdk/gdkwindow.c @@ -157,6 +157,9 @@ static GdkImage* gdk_window_copy_to_image (GdkDrawable *drawable, gint width, gint height); +static void gdk_window_set_cairo_target (GdkDrawable *drawable, + cairo_t *cr); + static void gdk_window_real_get_size (GdkDrawable *drawable, gint *width, gint *height); @@ -263,6 +266,7 @@ gdk_window_class_init (GdkWindowObjectClass *klass) drawable_class->get_colormap = gdk_window_real_get_colormap; drawable_class->get_visual = gdk_window_real_get_visual; drawable_class->_copy_to_image = gdk_window_copy_to_image; + drawable_class->set_cairo_target = gdk_window_set_cairo_target; drawable_class->get_clip_region = gdk_window_get_clip_region; drawable_class->get_visible_region = gdk_window_get_visible_region; drawable_class->get_composite_drawable = gdk_window_get_composite_drawable; @@ -2091,6 +2095,26 @@ gdk_window_copy_to_image (GdkDrawable *drawable, width, height); } +static void +gdk_window_set_cairo_target (GdkDrawable *drawable, + cairo_t *cr) +{ + GdkWindowObject *private = (GdkWindowObject*) drawable; + gint x_offset, y_offset; + + gdk_window_get_offsets (GDK_WINDOW (drawable), &x_offset, &y_offset); + + if (private->paint_stack) + { + GdkWindowPaint *paint = private->paint_stack->data; + gdk_drawable_set_cairo_target (paint->pixmap, cr); + } + else + gdk_drawable_set_cairo_target (private->impl, cr); + + cairo_translate (cr, - x_offset, - y_offset); +} + /* Code for dirty-region queueing */ static GSList *update_windows = NULL; diff --git a/gdk/x11/gdkdrawable-x11.c b/gdk/x11/gdkdrawable-x11.c index c6f3142072..19c7b9264a 100644 --- a/gdk/x11/gdkdrawable-x11.c +++ b/gdk/x11/gdkdrawable-x11.c @@ -147,6 +147,9 @@ static void gdk_x11_draw_trapezoids (GdkDrawable *drawable, GdkTrapezoid *trapezoids, gint n_trapezoids); +static void gdk_x11_set_cairo_target (GdkDrawable *drawable, + cairo_t *cr); + static void gdk_x11_set_colormap (GdkDrawable *drawable, GdkColormap *colormap); @@ -215,6 +218,8 @@ gdk_drawable_impl_x11_class_init (GdkDrawableImplX11Class *klass) drawable_class->draw_pixbuf = gdk_x11_draw_pixbuf; drawable_class->draw_trapezoids = gdk_x11_draw_trapezoids; + drawable_class->set_cairo_target = gdk_x11_set_cairo_target; + drawable_class->set_colormap = gdk_x11_set_colormap; drawable_class->get_colormap = gdk_x11_get_colormap; @@ -1558,6 +1563,51 @@ gdk_x11_draw_trapezoids (GdkDrawable *drawable, g_free (xtrapezoids); } +static cairo_surface_t * +gdk_x11_drawable_get_cairo_surface (GdkDrawable *drawable) +{ + GdkDrawableImplX11 *impl = GDK_DRAWABLE_IMPL_X11 (drawable); + GdkColormap *colormap; + GdkVisual *visual; + + if (GDK_IS_WINDOW_IMPL_X11 (drawable) && + GDK_WINDOW_DESTROYED (impl->wrapper)) + return NULL; + + colormap = gdk_drawable_get_colormap (drawable); + if (!colormap) + { + g_warning ("Using Cairo rendering requires the drawable argument to\n" + "have a specified colormap. All windows have a colormap,\n" + "however, pixmaps only have colormap by default if they\n" + "were created with a non-NULL window argument. Otherwise\n" + "a colormap must be set on them with gdk_drawable_set_colormap"); + return NULL; + } + + visual = gdk_colormap_get_visual (colormap); + + if (!impl->cairo_surface) + { + impl->cairo_surface = cairo_xlib_surface_create (GDK_SCREEN_XDISPLAY (impl->screen), + impl->xid, + GDK_VISUAL_XVISUAL (visual), + CAIRO_FORMAT_RGB24, + GDK_COLORMAP_XCOLORMAP (colormap)); + } + + return impl->cairo_surface; +} + +static void +gdk_x11_set_cairo_target (GdkDrawable *drawable, + cairo_t *cr) +{ + cairo_surface_t *surface = gdk_x11_drawable_get_cairo_surface (drawable); + if (surface) + cairo_set_target_surface (cr, surface); +} + /** * gdk_draw_rectangle_alpha_libgtk_only: * @drawable: The #GdkDrawable to draw on diff --git a/gdk/x11/gdkdrawable-x11.h b/gdk/x11/gdkdrawable-x11.h index 45c8e38b8d..1de1e50c3e 100644 --- a/gdk/x11/gdkdrawable-x11.h +++ b/gdk/x11/gdkdrawable-x11.h @@ -71,6 +71,7 @@ struct _GdkDrawableImplX11 GdkScreen *screen; XftDraw *xft_draw; + cairo_surface_t *cairo_surface; }; struct _GdkDrawableImplX11Class diff --git a/gdk/x11/gdkpixmap-x11.c b/gdk/x11/gdkpixmap-x11.c index 1b7776fd46..9590aace03 100644 --- a/gdk/x11/gdkpixmap-x11.c +++ b/gdk/x11/gdkpixmap-x11.c @@ -135,6 +135,12 @@ gdk_pixmap_impl_x11_finalize (GObject *object) if (draw_impl->xft_draw) XftDrawDestroy (draw_impl->xft_draw); + if (draw_impl->cairo_surface) + { + cairo_surface_destroy (draw_impl->cairo_surface); + draw_impl->cairo_surface = NULL; + } + if (!impl->is_foreign) XFreePixmap (GDK_DISPLAY_XDISPLAY (display), GDK_PIXMAP_XID (wrapper)); } diff --git a/gdk/x11/gdkwindow-x11.c b/gdk/x11/gdkwindow-x11.c index cb2b095ce7..3c86ba9dc0 100644 --- a/gdk/x11/gdkwindow-x11.c +++ b/gdk/x11/gdkwindow-x11.c @@ -1144,7 +1144,16 @@ _gdk_windowing_window_destroy (GdkWindow *window, draw_impl = GDK_DRAWABLE_IMPL_X11 (private->impl); if (draw_impl->xft_draw) - XftDrawDestroy (draw_impl->xft_draw); + { + XftDrawDestroy (draw_impl->xft_draw); + draw_impl->xft_draw = NULL; + } + + if (draw_impl->cairo_surface) + { + cairo_surface_destroy (draw_impl->cairo_surface); + draw_impl->cairo_surface = NULL; + } if (!recursing && !foreign_destroy) { diff --git a/tests/.cvsignore b/tests/.cvsignore index 5f317de9b7..32d1b68443 100644 --- a/tests/.cvsignore +++ b/tests/.cvsignore @@ -14,6 +14,7 @@ pixbuf-threads simple stresstest-toolbar testactions +testcairo testcalendar testcombo testcombochange diff --git a/tests/Makefile.am b/tests/Makefile.am index eea2da8b8b..56cad51240 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -28,6 +28,7 @@ endif noinst_PROGRAMS = \ simple \ + testcairo \ testcalendar \ testcombo \ testcombochange \ @@ -72,6 +73,7 @@ noinst_PROGRAMS = \ simple_DEPENDENCIES = $(TEST_DEPS) testicontheme_DEPENDENCIES = $(TEST_DEPS) testiconview_DEPENDENCIES = $(TEST_DEPS) +testcairo_DEPENDENCIES = $(TEST_DEPS) testcalendar_DEPENDENCIES = $(TEST_DEPS) testcombo_DEPENDENCIES = $(TEST_DEPS) testcombochange_DEPENDENCIES = $(TEST_DEPS) @@ -106,6 +108,7 @@ testmerge_DEPENDENCIES = $(TEST_DEPS) testactions_DEPENDENCIES = $(TEST_DEPS) simple_LDADD = $(LDADDS) +testcairo_LDADD = $(LDADDS) testcalendar_LDADD = $(LDADDS) testcombo_LDADD = $(LDADDS) testcombochange_LDADD = $(LDADDS) diff --git a/tests/testcairo.c b/tests/testcairo.c new file mode 100644 index 0000000000..9759adf0d3 --- /dev/null +++ b/tests/testcairo.c @@ -0,0 +1,243 @@ +/* testimage.c + * Copyright (C) 2005 Red Hat, Inc. + * Based on cairo-demo/X11/cairo-knockout.c + * + * Author: Owen Taylor + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + +#include + +static void +oval_path (cairo_t *cr, + double xc, double yc, + double xr, double yr) +{ + cairo_matrix_t *matrix; + + matrix = cairo_matrix_create (); + cairo_current_matrix (cr, matrix); + + cairo_translate (cr, xc, yc); + cairo_scale (cr, 1.0, yr / xr); + cairo_move_to (cr, xr, 0.0); + cairo_arc (cr, + 0, 0, + xr, + 0, 2 * G_PI); + cairo_close_path (cr); + + cairo_set_matrix (cr, matrix); + cairo_matrix_destroy (matrix); +} + +/* Create a path that is a circular oval with radii xr, yr at xc, + * yc. + */ +/* Fill the given area with checks in the standard style + * for showing compositing effects. + * + * It would make sense to do this as a repeating surface, + * but most implementations of RENDER currently have broken + * implementations of repeat + transform, even when the + * transform is a translation. + */ +static void +fill_checks (cairo_t *cr, + int x, int y, + int width, int height) +{ + int i, j; + +#define CHECK_SIZE 32 + + cairo_rectangle (cr, x, y, width, height); + cairo_set_rgb_color (cr, 0.4, 0.4, 0.4); + cairo_fill (cr); + + /* Only works for CHECK_SIZE a power of 2 */ + j = x & (-CHECK_SIZE); + + for (; j < height; j += CHECK_SIZE) + { + i = y & (-CHECK_SIZE); + for (; i < width; i += CHECK_SIZE) + if ((i / CHECK_SIZE + j / CHECK_SIZE) % 2 == 0) + cairo_rectangle (cr, i, j, CHECK_SIZE, CHECK_SIZE); + } + + cairo_set_rgb_color (cr, 0.7, 0.7, 0.7); + cairo_fill (cr); +} + +/* Draw a red, green, and blue circle equally spaced inside + * the larger circle of radius r at (xc, yc) + */ +static void +draw_3circles (cairo_t *cr, + double xc, double yc, + double radius) +{ + double subradius = radius * (2 / 3. - 0.1); + + cairo_set_rgb_color (cr, 1., 0., 0.); + oval_path (cr, + xc + radius / 3. * cos (G_PI * (0.5)), + yc - radius / 3. * sin (G_PI * (0.5)), + subradius, subradius); + cairo_fill (cr); + + cairo_set_rgb_color (cr, 0., 1., 0.); + oval_path (cr, + xc + radius / 3. * cos (G_PI * (0.5 + 2/.3)), + yc - radius / 3. * sin (G_PI * (0.5 + 2/.3)), + subradius, subradius); + cairo_fill (cr); + + cairo_set_rgb_color (cr, 0., 0., 1.); + oval_path (cr, + xc + radius / 3. * cos (G_PI * (0.5 + 4/.3)), + yc - radius / 3. * sin (G_PI * (0.5 + 4/.3)), + subradius, subradius); + cairo_fill (cr); +} + +static void +draw (cairo_t *cr, + int width, + int height) +{ + cairo_surface_t *overlay, *punch, *circles; + + /* Fill the background */ + double radius = 0.5 * (width < height ? width : height) - 10; + double xc = width / 2.; + double yc = height / 2.; + + overlay = cairo_surface_create_similar (cairo_current_target_surface (cr), + CAIRO_FORMAT_ARGB32, + width, height); + if (overlay == NULL) + return; + + punch = cairo_surface_create_similar (cairo_current_target_surface (cr), + CAIRO_FORMAT_A8, + width, height); + if (punch == NULL) + return; + + circles = cairo_surface_create_similar (cairo_current_target_surface (cr), + CAIRO_FORMAT_ARGB32, + width, height); + if (circles == NULL) + return; + + fill_checks (cr, 0, 0, width, height); + + cairo_save (cr); + cairo_set_target_surface (cr, overlay); + cairo_identity_matrix (cr); + + /* Draw a black circle on the overlay + */ + cairo_set_rgb_color (cr, 0., 0., 0.); + oval_path (cr, xc, yc, radius, radius); + cairo_fill (cr); + + cairo_save (cr); + cairo_set_target_surface (cr, punch); + + /* Draw 3 circles to the punch surface, then cut + * that out of the main circle in the overlay + */ + draw_3circles (cr, xc, yc, radius); + + cairo_restore (cr); + + cairo_set_operator (cr, CAIRO_OPERATOR_OUT_REVERSE); + cairo_show_surface (cr, punch, width, height); + + /* Now draw the 3 circles in a subgroup again + * at half intensity, and use OperatorAdd to join up + * without seams. + */ + cairo_save (cr); + cairo_set_target_surface (cr, circles); + + cairo_set_alpha (cr, 0.5); + cairo_set_operator (cr, CAIRO_OPERATOR_OVER); + draw_3circles (cr, xc, yc, radius); + + cairo_restore (cr); + + cairo_set_operator (cr, CAIRO_OPERATOR_ADD); + cairo_show_surface (cr, circles, width, height); + + cairo_restore (cr); + + cairo_show_surface (cr, overlay, width, height); + + cairo_surface_destroy (overlay); + cairo_surface_destroy (punch); + cairo_surface_destroy (circles); +} + +static gboolean +on_expose_event (GtkWidget *widget, + GdkEventExpose *event, + gpointer data) +{ + cairo_t *cr; + + cr = cairo_create (); + gdk_drawable_set_cairo_target (GDK_DRAWABLE (widget->window), cr); + + draw (cr, widget->allocation.width, widget->allocation.height); + + cairo_destroy (cr); + + return FALSE; +} + +int +main (int argc, char **argv) +{ + GtkWidget *window, *darea; + + gtk_init (&argc, &argv); + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + + gtk_window_set_default_size (GTK_WINDOW (window), 400, 400); + gtk_window_set_title (GTK_WINDOW (window), "cairo: Knockout Groups"); + + darea = gtk_drawing_area_new (); + gtk_container_add (GTK_CONTAINER (window), darea); + + g_signal_connect (darea, "expose-event", + G_CALLBACK (on_expose_event), NULL); + g_signal_connect (window, "destroy-event", + G_CALLBACK (gtk_main_quit), NULL); + + gtk_widget_show_all (window); + + gtk_main (); + + return 0; +} diff --git a/tests/testtreeflow.c b/tests/testtreeflow.c index 6f87df0cba..979e1c8a8d 100644 --- a/tests/testtreeflow.c +++ b/tests/testtreeflow.c @@ -2,7 +2,7 @@ #include GtkTreeModel *model = NULL; -static GRand *rand = NULL; +static GRand *grand = NULL; GtkTreeSelection *selection = NULL; enum { @@ -32,12 +32,12 @@ initialize_model (void) GtkTreeIter iter; model = (GtkTreeModel *) gtk_list_store_new (NUM_COLUMNS, G_TYPE_STRING); - rand = g_rand_new (); + grand = g_rand_new (); for (i = 0; i < NUM_ROWS; i++) { gtk_list_store_append (GTK_LIST_STORE (model), &iter); gtk_list_store_set (GTK_LIST_STORE (model), &iter, - TEXT_COLUMN, words[g_rand_int_range (rand, 0, NUM_WORDS)], + TEXT_COLUMN, words[g_rand_int_range (grand, 0, NUM_WORDS)], -1); } } @@ -50,7 +50,7 @@ futz_row (void) GtkTreeIter iter; GtkTreeIter iter2; - i = g_rand_int_range (rand, 0, + i = g_rand_int_range (grand, 0, gtk_tree_model_iter_n_children (model, NULL)); path = gtk_tree_path_new (); gtk_tree_path_append_index (path, i); @@ -59,14 +59,14 @@ futz_row (void) if (gtk_tree_selection_iter_is_selected (selection, &iter)) return; - switch (g_rand_int_range (rand, 0, 3)) + switch (g_rand_int_range (grand, 0, 3)) { case 0: /* insert */ gtk_list_store_insert_after (GTK_LIST_STORE (model), &iter2, &iter); gtk_list_store_set (GTK_LIST_STORE (model), &iter2, - TEXT_COLUMN, words[g_rand_int_range (rand, 0, NUM_WORDS)], + TEXT_COLUMN, words[g_rand_int_range (grand, 0, NUM_WORDS)], -1); break; case 1: @@ -81,7 +81,7 @@ futz_row (void) if (gtk_tree_model_iter_n_children (model, NULL) == 0) return; gtk_list_store_set (GTK_LIST_STORE (model), &iter, - TEXT_COLUMN, words[g_rand_int_range (rand, 0, NUM_WORDS)], + TEXT_COLUMN, words[g_rand_int_range (grand, 0, NUM_WORDS)], -1); break; } -- 2.30.2